load R packages

library(tidyverse)
library(umap)

load gene expression data in FPKM format

luad_fpkm <- read_tsv("./data/processed/TCGA-GDC/rna_seq/tcga_luad_PrimaryTumor_FPKM.txt.gz")
lusc_fpkm <- read_tsv("./data/processed/TCGA-GDC/rna_seq/tcga_lusc_PrimaryTumor_FPKM.txt.gz")

load samples metadata

luad_metadata <- read_tsv("./data/processed/metadata/tcga_luad_metadata_pancancer_atlas.txt")
lusc_metadata <- read_tsv("./data/processed/metadata/tcga_lusc_metadata_pancancer_atlas.txt")

load gene annotation

gene_annot <- read_tsv("./data/raw/TCGA-GDC/rna_seq/gene_annotation/gencode.gene.info.v22.tsv")

select only protein coding and lincRNA genes

sel_genes <- gene_annot %>%
  filter(gene_type %in% c("protein_coding", "lincRNA"))

luad_fpkm <- luad_fpkm %>%
  semi_join(sel_genes, by = c("gene" = "gene_id"))

lusc_fpkm <- lusc_fpkm %>%
  semi_join(sel_genes, by = c("gene" = "gene_id"))

select only the genes with median fpkm > 1 and transform values to log2

luad_fpkm <- luad_fpkm %>%
  pivot_longer(-gene, names_to = "sample", values_to = "fpkm") %>%
  group_by(gene) %>%
  filter(median(fpkm) > 1) %>%
  ungroup() %>%
  mutate(fpkm = log2(fpkm + 1)) %>%
  mutate(sample = str_sub(sample, 1, 12)) %>%
  pivot_wider(names_from = "sample", values_from = "fpkm")

lusc_fpkm <- lusc_fpkm %>%
  pivot_longer(-gene, names_to = "sample", values_to = "fpkm") %>%
  group_by(gene) %>%
  filter(median(fpkm) > 1) %>%
  ungroup() %>%
  mutate(fpkm = log2(fpkm + 1)) %>%
  mutate(sample = str_sub(sample, 1, 12)) %>%
  pivot_wider(names_from = "sample", values_from = "fpkm")

dimensionality reduction across both cohorts

set up a matrix with both cohorts

tcga_lung <- inner_join(luad_fpkm, lusc_fpkm, by = "gene") %>%
  column_to_rownames(var = "gene") %>%
  as.matrix() %>%
  t()

UMAP analysis across both cohorts

tcga_lung_umap <- umap(tcga_lung)

tcga_metadata <- bind_rows(luad_metadata[, c("sample", "tcga_cohort")], lusc_metadata[, c("sample", "tcga_cohort")]) %>%
  rename(cohort = tcga_cohort)

tcga_lung_umap_plot <- tcga_lung_umap %>%
  pluck("layout") %>%
  as.data.frame() %>%
  rownames_to_column(var = "sample") %>%
  as_tibble() %>%
  rename(UMAP1 = V1, UMAP2 = V2) %>%
  inner_join(tcga_metadata, by = "sample") %>%
  ggplot(mapping = aes(x = UMAP1, y = UMAP2, color = cohort)) +
    geom_point()
tcga_lung_umap_plot


tcga_lung_umap_plot <- tcga_lung_umap %>%
  pluck("layout") %>%
  as.data.frame() %>%
  rownames_to_column(var = "sample") %>%
  as_tibble() %>%
  rename(UMAP1 = V1, UMAP2 = V2) %>%
  filter(UMAP1 > -20) %>%
  inner_join(tcga_metadata, by = "sample") %>%
  ggplot(mapping = aes(x = UMAP1, y = UMAP2, color = cohort)) +
    geom_point()
tcga_lung_umap_plot

PCA analysis across both cohorts

tcga_lung_pca <- prcomp(tcga_lung, center = T, scale. = T)

tcga_lung_pca_plot <- tcga_lung_pca %>%
  pluck("x") %>%
  as.data.frame() %>%
  rownames_to_column(var = "sample") %>%
  as_tibble() %>%
  inner_join(tcga_metadata, by = "sample") %>%
  ggplot(mapping = aes(x = PC1, y = PC2, color = cohort)) +
  geom_point()
tcga_lung_pca_plot

dimensionality reduction across LUAD cohort

set up a matrix with LUAD cohort

luad_mat <- luad_fpkm %>%
  column_to_rownames(var = "gene") %>%
  as.matrix() %>%
  t()

UMAP analysis across LUAD cohort

luad_umap <- umap(luad_mat)

luad_umap_temp_plot <- luad_umap %>%
  pluck("layout") %>%
  as.data.frame() %>%
  rownames_to_column(var = "sample") %>%
  as_tibble() %>%
  rename(UMAP1 = V1, UMAP2 = V2) %>%
  inner_join(luad_metadata, by = "sample") %>%
  ggplot(mapping = aes(x = UMAP1, y = UMAP2))

luad_umap_plot <- luad_umap_temp_plot +
  geom_point(mapping = aes(color = gender))
luad_umap_plot


luad_umap_plot <- luad_umap_temp_plot +
  geom_point(mapping = aes(color = race))
luad_umap_plot


luad_umap_plot <- luad_umap_temp_plot +
  geom_point(mapping = aes(color = ethnicity))
luad_umap_plot


luad_umap_plot <- luad_umap_temp_plot +
  geom_point(mapping = aes(color = age_at_diagnosis))
luad_umap_plot


luad_umap_plot <- luad_umap_temp_plot +
  geom_point(mapping = aes(color = tissue_source_site))
luad_umap_plot


luad_umap_plot <- luad_umap_temp_plot +
  geom_point(mapping = aes(color = pathologic_stage))
luad_umap_plot


luad_umap_plot <- luad_umap_temp_plot +
  geom_point(mapping = aes(color = tobacco_smoking_history))
luad_umap_plot


luad_umap_plot <- luad_umap_temp_plot +
  geom_point(mapping = aes(color = smoker))
luad_umap_plot


luad_umap_plot <- luad_umap_temp_plot +
  geom_point(mapping = aes(color = histological_type))
luad_umap_plot

PCA analysis across LUAD cohort

luad_pca <- prcomp(luad_mat, center = T, scale. = T)

luad_pca_temp_plot <- luad_pca %>%
  pluck("x") %>%
  as.data.frame() %>%
  rownames_to_column(var = "sample") %>%
  as_tibble() %>%
  inner_join(luad_metadata, by = "sample") %>%
  ggplot(mapping = aes(x = PC1, y = PC2))

luad_pca_plot <- luad_pca_temp_plot +
  geom_point(mapping = aes(color = gender))
luad_pca_plot


luad_pca_plot <- luad_pca_temp_plot +
  geom_point(mapping = aes(color = race))
luad_pca_plot


luad_pca_plot <- luad_pca_temp_plot +
  geom_point(mapping = aes(color = ethnicity))
luad_pca_plot


luad_pca_plot <- luad_pca_temp_plot +
  geom_point(mapping = aes(color = age_at_diagnosis))
luad_pca_plot


luad_pca_plot <- luad_pca_temp_plot +
  geom_point(mapping = aes(color = tissue_source_site))
luad_pca_plot


luad_pca_plot <- luad_pca_temp_plot +
  geom_point(mapping = aes(color = pathologic_stage))
luad_pca_plot


luad_pca_plot <- luad_pca_temp_plot +
  geom_point(mapping = aes(color = tobacco_smoking_history))
luad_pca_plot


luad_pca_plot <- luad_pca_temp_plot +
  geom_point(mapping = aes(color = smoker))
luad_pca_plot


luad_pca_plot <- luad_pca_temp_plot +
  geom_point(mapping = aes(color = histological_type))
luad_pca_plot

hierachical clustering to select outlier samples use default distance measure (eucledian) and agglomeration method (complete)

luad_hc <- hclust(dist(luad_mat))

plot(luad_hc, cex = 0.5)


luad_clusters <- cutree(luad_hc, h = 200)
luad_clusters <- tibble(sample = names(luad_clusters), cluster = unname(luad_clusters))

write_tsv(x = luad_clusters, file = "./output/files/02_exploratory_analysis/tcga_luad_outlier_samples_hclust_200_height.txt")

luad_umap2 <- umap(luad_mat[rownames(luad_mat) %in% luad_clusters[luad_clusters$cluster == 1, ]$sample, ])

luad_umap_temp_plot2 <- luad_umap2 %>%
  pluck("layout") %>%
  as.data.frame() %>%
  rownames_to_column(var = "sample") %>%
  as_tibble() %>%
  rename(UMAP1 = V1, UMAP2 = V2) %>%
  inner_join(luad_metadata, by = "sample") %>%
  ggplot(mapping = aes(x = UMAP1, y = UMAP2))

luad_umap_plot2 <- luad_umap_temp_plot2 +
  geom_point(mapping = aes(color = tissue_source_site))
luad_umap_plot2



luad_pca2 <- prcomp(luad_mat[rownames(luad_mat) %in% luad_clusters[luad_clusters$cluster == 1, ]$sample, ], center = T, scale. = T)

luad_pca_temp_plot2 <- luad_pca2 %>%
  pluck("x") %>%
  as.data.frame() %>%
  rownames_to_column(var = "sample") %>%
  as_tibble() %>%
  inner_join(luad_metadata, by = "sample") %>%
  ggplot(mapping = aes(x = PC1, y = PC2))

luad_pca_plot2 <- luad_pca_temp_plot2 +
  geom_point(mapping = aes(color = tissue_source_site))
luad_pca_plot2

dimensionality reduction across LUSC cohort

set up a matrix with LUSC cohort

lusc_mat <- lusc_fpkm %>%
  column_to_rownames(var = "gene") %>%
  as.matrix() %>%
  t()

UMAP analysis across LUSC cohort

lusc_umap <- umap(lusc_mat)

lusc_umap_temp_plot <- lusc_umap %>%
  pluck("layout") %>%
  as.data.frame() %>%
  rownames_to_column(var = "sample") %>%
  as_tibble() %>%
  rename(UMAP1 = V1, UMAP2 = V2) %>%
  inner_join(lusc_metadata, by = "sample") %>%
  ggplot(mapping = aes(x = UMAP1, y = UMAP2))

lusc_umap_plot <- lusc_umap_temp_plot +
  geom_point(mapping = aes(color = gender))
lusc_umap_plot


lusc_umap_plot <- lusc_umap_temp_plot +
  geom_point(mapping = aes(color = race))
lusc_umap_plot


lusc_umap_plot <- lusc_umap_temp_plot +
  geom_point(mapping = aes(color = ethnicity))
lusc_umap_plot


lusc_umap_plot <- lusc_umap_temp_plot +
  geom_point(mapping = aes(color = age_at_diagnosis))
lusc_umap_plot


lusc_umap_plot <- lusc_umap_temp_plot +
  geom_point(mapping = aes(color = tissue_source_site))
lusc_umap_plot


lusc_umap_plot <- lusc_umap_temp_plot +
  geom_point(mapping = aes(color = pathologic_stage))
lusc_umap_plot


lusc_umap_plot <- lusc_umap_temp_plot +
  geom_point(mapping = aes(color = tobacco_smoking_history))
lusc_umap_plot


lusc_umap_plot <- lusc_umap_temp_plot +
  geom_point(mapping = aes(color = smoker))
lusc_umap_plot


lusc_umap_plot <- lusc_umap_temp_plot +
  geom_point(mapping = aes(color = histological_type))
lusc_umap_plot

PCA analysis across LUSC cohort

lusc_pca <- prcomp(lusc_mat, center = T, scale. = T)

lusc_pca_temp_plot <- lusc_pca %>%
  pluck("x") %>%
  as.data.frame() %>%
  rownames_to_column(var = "sample") %>%
  as_tibble() %>%
  inner_join(lusc_metadata, by = "sample") %>%
  ggplot(mapping = aes(x = PC1, y = PC2))

lusc_pca_plot <- lusc_pca_temp_plot +
  geom_point(mapping = aes(color = gender))
lusc_pca_plot


lusc_pca_plot <- lusc_pca_temp_plot +
  geom_point(mapping = aes(color = race))
lusc_pca_plot


lusc_pca_plot <- lusc_pca_temp_plot +
  geom_point(mapping = aes(color = ethnicity))
lusc_pca_plot


lusc_pca_plot <- lusc_pca_temp_plot +
  geom_point(mapping = aes(color = age_at_diagnosis))
lusc_pca_plot


lusc_pca_plot <- lusc_pca_temp_plot +
  geom_point(mapping = aes(color = tissue_source_site))
lusc_pca_plot


lusc_pca_plot <- lusc_pca_temp_plot +
  geom_point(mapping = aes(color = pathologic_stage))
lusc_pca_plot


lusc_pca_plot <- lusc_pca_temp_plot +
  geom_point(mapping = aes(color = tobacco_smoking_history))
lusc_pca_plot


lusc_pca_plot <- lusc_pca_temp_plot +
  geom_point(mapping = aes(color = smoker))
lusc_pca_plot


lusc_pca_plot <- lusc_pca_temp_plot +
  geom_point(mapping = aes(color = histological_type))
lusc_pca_plot

hierachical clustering to select outlier samples use default distance measure (eucledian) and agglomeration method (complete)

lusc_hc <- hclust(dist(lusc_mat))

plot(lusc_hc, cex = 0.5)


lusc_clusters <- cutree(lusc_hc, h = 190)
lusc_clusters <- tibble(sample = names(lusc_clusters), cluster = unname(lusc_clusters))

write_tsv(x = lusc_clusters, file = "./output/files/02_exploratory_analysis/tcga_lusc_outlier_samples_hclust_190_height.txt")

lusc_umap2 <- umap(lusc_mat[rownames(lusc_mat) %in% lusc_clusters[lusc_clusters$cluster == 1, ]$sample, ])

lusc_umap_temp_plot2 <- lusc_umap2 %>%
  pluck("layout") %>%
  as.data.frame() %>%
  rownames_to_column(var = "sample") %>%
  as_tibble() %>%
  rename(UMAP1 = V1, UMAP2 = V2) %>%
  inner_join(lusc_metadata, by = "sample") %>%
  ggplot(mapping = aes(x = UMAP1, y = UMAP2))

lusc_umap_plot2 <- lusc_umap_temp_plot2 +
  geom_point(mapping = aes(color = smoker))
lusc_umap_plot2



lusc_pca2 <- prcomp(lusc_mat[rownames(lusc_mat) %in% lusc_clusters[lusc_clusters$cluster == 1, ]$sample, ], center = T, scale. = T)

lusc_pca_temp_plot2 <- lusc_pca2 %>%
  pluck("x") %>%
  as.data.frame() %>%
  rownames_to_column(var = "sample") %>%
  as_tibble() %>%
  inner_join(lusc_metadata, by = "sample") %>%
  ggplot(mapping = aes(x = PC1, y = PC2))

lusc_pca_plot2 <- lusc_pca_temp_plot2 +
  geom_point(mapping = aes(color = smoker))
lusc_pca_plot2

LS0tCnRpdGxlOiAiTHVuZyBjYW5jZXIgZGltZW5zaW9uYWxpdHkgcmVkdWN0aW9uIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRikKYGBgCgoKbG9hZCBSIHBhY2thZ2VzCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeSh1bWFwKQpgYGAKCmxvYWQgZ2VuZSBleHByZXNzaW9uIGRhdGEgaW4gRlBLTSBmb3JtYXQKYGBge3J9Cmx1YWRfZnBrbSA8LSByZWFkX3RzdigiLi9kYXRhL3Byb2Nlc3NlZC9UQ0dBLUdEQy9ybmFfc2VxL3RjZ2FfbHVhZF9QcmltYXJ5VHVtb3JfRlBLTS50eHQuZ3oiKQpsdXNjX2Zwa20gPC0gcmVhZF90c3YoIi4vZGF0YS9wcm9jZXNzZWQvVENHQS1HREMvcm5hX3NlcS90Y2dhX2x1c2NfUHJpbWFyeVR1bW9yX0ZQS00udHh0Lmd6IikKYGBgCgoKbG9hZCBzYW1wbGVzIG1ldGFkYXRhCmBgYHtyfQpsdWFkX21ldGFkYXRhIDwtIHJlYWRfdHN2KCIuL2RhdGEvcHJvY2Vzc2VkL21ldGFkYXRhL3RjZ2FfbHVhZF9tZXRhZGF0YV9wYW5jYW5jZXJfYXRsYXMudHh0IikKbHVzY19tZXRhZGF0YSA8LSByZWFkX3RzdigiLi9kYXRhL3Byb2Nlc3NlZC9tZXRhZGF0YS90Y2dhX2x1c2NfbWV0YWRhdGFfcGFuY2FuY2VyX2F0bGFzLnR4dCIpCmBgYAoKCmxvYWQgZ2VuZSBhbm5vdGF0aW9uCmBgYHtyfQpnZW5lX2Fubm90IDwtIHJlYWRfdHN2KCIuL2RhdGEvcmF3L1RDR0EtR0RDL3JuYV9zZXEvZ2VuZV9hbm5vdGF0aW9uL2dlbmNvZGUuZ2VuZS5pbmZvLnYyMi50c3YiKQpgYGAKCgpzZWxlY3Qgb25seSBwcm90ZWluIGNvZGluZyBhbmQgbGluY1JOQSBnZW5lcwpgYGB7cn0Kc2VsX2dlbmVzIDwtIGdlbmVfYW5ub3QgJT4lCiAgZmlsdGVyKGdlbmVfdHlwZSAlaW4lIGMoInByb3RlaW5fY29kaW5nIiwgImxpbmNSTkEiKSkKCmx1YWRfZnBrbSA8LSBsdWFkX2Zwa20gJT4lCiAgc2VtaV9qb2luKHNlbF9nZW5lcywgYnkgPSBjKCJnZW5lIiA9ICJnZW5lX2lkIikpCgpsdXNjX2Zwa20gPC0gbHVzY19mcGttICU+JQogIHNlbWlfam9pbihzZWxfZ2VuZXMsIGJ5ID0gYygiZ2VuZSIgPSAiZ2VuZV9pZCIpKQpgYGAKCgpzZWxlY3Qgb25seSB0aGUgZ2VuZXMgd2l0aCBtZWRpYW4gZnBrbSA+IDEgYW5kIHRyYW5zZm9ybSB2YWx1ZXMgdG8gbG9nMgpgYGB7cn0KbHVhZF9mcGttIDwtIGx1YWRfZnBrbSAlPiUKICBwaXZvdF9sb25nZXIoLWdlbmUsIG5hbWVzX3RvID0gInNhbXBsZSIsIHZhbHVlc190byA9ICJmcGttIikgJT4lCiAgZ3JvdXBfYnkoZ2VuZSkgJT4lCiAgZmlsdGVyKG1lZGlhbihmcGttKSA+IDEpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoZnBrbSA9IGxvZzIoZnBrbSArIDEpKSAlPiUKICBtdXRhdGUoc2FtcGxlID0gc3RyX3N1YihzYW1wbGUsIDEsIDEyKSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9ICJzYW1wbGUiLCB2YWx1ZXNfZnJvbSA9ICJmcGttIikKCmx1c2NfZnBrbSA8LSBsdXNjX2Zwa20gJT4lCiAgcGl2b3RfbG9uZ2VyKC1nZW5lLCBuYW1lc190byA9ICJzYW1wbGUiLCB2YWx1ZXNfdG8gPSAiZnBrbSIpICU+JQogIGdyb3VwX2J5KGdlbmUpICU+JQogIGZpbHRlcihtZWRpYW4oZnBrbSkgPiAxKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGZwa20gPSBsb2cyKGZwa20gKyAxKSkgJT4lCiAgbXV0YXRlKHNhbXBsZSA9IHN0cl9zdWIoc2FtcGxlLCAxLCAxMikpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSAic2FtcGxlIiwgdmFsdWVzX2Zyb20gPSAiZnBrbSIpCmBgYAoKCiMjIyBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gYWNyb3NzIGJvdGggY29ob3J0cwoKc2V0IHVwIGEgbWF0cml4IHdpdGggYm90aCBjb2hvcnRzCmBgYHtyfQp0Y2dhX2x1bmcgPC0gaW5uZXJfam9pbihsdWFkX2Zwa20sIGx1c2NfZnBrbSwgYnkgPSAiZ2VuZSIpICU+JQogIGNvbHVtbl90b19yb3duYW1lcyh2YXIgPSAiZ2VuZSIpICU+JQogIGFzLm1hdHJpeCgpICU+JQogIHQoKQpgYGAKCgpVTUFQIGFuYWx5c2lzIGFjcm9zcyBib3RoIGNvaG9ydHMKYGBge3J9CnRjZ2FfbHVuZ191bWFwIDwtIHVtYXAodGNnYV9sdW5nKQoKdGNnYV9tZXRhZGF0YSA8LSBiaW5kX3Jvd3MobHVhZF9tZXRhZGF0YVssIGMoInNhbXBsZSIsICJ0Y2dhX2NvaG9ydCIpXSwgbHVzY19tZXRhZGF0YVssIGMoInNhbXBsZSIsICJ0Y2dhX2NvaG9ydCIpXSkgJT4lCiAgcmVuYW1lKGNvaG9ydCA9IHRjZ2FfY29ob3J0KQoKdGNnYV9sdW5nX3VtYXBfcGxvdCA8LSB0Y2dhX2x1bmdfdW1hcCAlPiUKICBwbHVjaygibGF5b3V0IikgJT4lCiAgYXMuZGF0YS5mcmFtZSgpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAic2FtcGxlIikgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcmVuYW1lKFVNQVAxID0gVjEsIFVNQVAyID0gVjIpICU+JQogIGlubmVyX2pvaW4odGNnYV9tZXRhZGF0YSwgYnkgPSAic2FtcGxlIikgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFVNQVAxLCB5ID0gVU1BUDIsIGNvbG9yID0gY29ob3J0KSkgKwogICAgZ2VvbV9wb2ludCgpCnRjZ2FfbHVuZ191bWFwX3Bsb3QKCnRjZ2FfbHVuZ191bWFwX3Bsb3QgPC0gdGNnYV9sdW5nX3VtYXAgJT4lCiAgcGx1Y2soImxheW91dCIpICU+JQogIGFzLmRhdGEuZnJhbWUoKSAlPiUKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInNhbXBsZSIpICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHJlbmFtZShVTUFQMSA9IFYxLCBVTUFQMiA9IFYyKSAlPiUKICBmaWx0ZXIoVU1BUDEgPiAtMjApICU+JQogIGlubmVyX2pvaW4odGNnYV9tZXRhZGF0YSwgYnkgPSAic2FtcGxlIikgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFVNQVAxLCB5ID0gVU1BUDIsIGNvbG9yID0gY29ob3J0KSkgKwogICAgZ2VvbV9wb2ludCgpCnRjZ2FfbHVuZ191bWFwX3Bsb3QKYGBgCgoKUENBIGFuYWx5c2lzIGFjcm9zcyBib3RoIGNvaG9ydHMKYGBge3J9CnRjZ2FfbHVuZ19wY2EgPC0gcHJjb21wKHRjZ2FfbHVuZywgY2VudGVyID0gVCwgc2NhbGUuID0gVCkKCnRjZ2FfbHVuZ19wY2FfcGxvdCA8LSB0Y2dhX2x1bmdfcGNhICU+JQogIHBsdWNrKCJ4IikgJT4lCiAgYXMuZGF0YS5mcmFtZSgpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAic2FtcGxlIikgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgaW5uZXJfam9pbih0Y2dhX21ldGFkYXRhLCBieSA9ICJzYW1wbGUiKSAlPiUKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gUEMxLCB5ID0gUEMyLCBjb2xvciA9IGNvaG9ydCkpICsKICBnZW9tX3BvaW50KCkKdGNnYV9sdW5nX3BjYV9wbG90CmBgYAoKCiMjIyBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gYWNyb3NzIExVQUQgY29ob3J0CgpzZXQgdXAgYSBtYXRyaXggd2l0aCBMVUFEIGNvaG9ydApgYGB7cn0KbHVhZF9tYXQgPC0gbHVhZF9mcGttICU+JQogIGNvbHVtbl90b19yb3duYW1lcyh2YXIgPSAiZ2VuZSIpICU+JQogIGFzLm1hdHJpeCgpICU+JQogIHQoKQpgYGAKCgpVTUFQIGFuYWx5c2lzIGFjcm9zcyBMVUFEIGNvaG9ydApgYGB7cn0KbHVhZF91bWFwIDwtIHVtYXAobHVhZF9tYXQpCgpsdWFkX3VtYXBfdGVtcF9wbG90IDwtIGx1YWRfdW1hcCAlPiUKICBwbHVjaygibGF5b3V0IikgJT4lCiAgYXMuZGF0YS5mcmFtZSgpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAic2FtcGxlIikgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcmVuYW1lKFVNQVAxID0gVjEsIFVNQVAyID0gVjIpICU+JQogIGlubmVyX2pvaW4obHVhZF9tZXRhZGF0YSwgYnkgPSAic2FtcGxlIikgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFVNQVAxLCB5ID0gVU1BUDIpKQoKbHVhZF91bWFwX3Bsb3QgPC0gbHVhZF91bWFwX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gZ2VuZGVyKSkKbHVhZF91bWFwX3Bsb3QKCmx1YWRfdW1hcF9wbG90IDwtIGx1YWRfdW1hcF90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IHJhY2UpKQpsdWFkX3VtYXBfcGxvdAoKbHVhZF91bWFwX3Bsb3QgPC0gbHVhZF91bWFwX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gZXRobmljaXR5KSkKbHVhZF91bWFwX3Bsb3QKCmx1YWRfdW1hcF9wbG90IDwtIGx1YWRfdW1hcF90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IGFnZV9hdF9kaWFnbm9zaXMpKQpsdWFkX3VtYXBfcGxvdAoKbHVhZF91bWFwX3Bsb3QgPC0gbHVhZF91bWFwX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gdGlzc3VlX3NvdXJjZV9zaXRlKSkKbHVhZF91bWFwX3Bsb3QKCmx1YWRfdW1hcF9wbG90IDwtIGx1YWRfdW1hcF90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IHBhdGhvbG9naWNfc3RhZ2UpKQpsdWFkX3VtYXBfcGxvdAoKbHVhZF91bWFwX3Bsb3QgPC0gbHVhZF91bWFwX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gdG9iYWNjb19zbW9raW5nX2hpc3RvcnkpKQpsdWFkX3VtYXBfcGxvdAoKbHVhZF91bWFwX3Bsb3QgPC0gbHVhZF91bWFwX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gc21va2VyKSkKbHVhZF91bWFwX3Bsb3QKCmx1YWRfdW1hcF9wbG90IDwtIGx1YWRfdW1hcF90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IGhpc3RvbG9naWNhbF90eXBlKSkKbHVhZF91bWFwX3Bsb3QKYGBgCgoKUENBIGFuYWx5c2lzIGFjcm9zcyBMVUFEIGNvaG9ydApgYGB7cn0KbHVhZF9wY2EgPC0gcHJjb21wKGx1YWRfbWF0LCBjZW50ZXIgPSBULCBzY2FsZS4gPSBUKQoKbHVhZF9wY2FfdGVtcF9wbG90IDwtIGx1YWRfcGNhICU+JQogIHBsdWNrKCJ4IikgJT4lCiAgYXMuZGF0YS5mcmFtZSgpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAic2FtcGxlIikgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgaW5uZXJfam9pbihsdWFkX21ldGFkYXRhLCBieSA9ICJzYW1wbGUiKSAlPiUKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gUEMxLCB5ID0gUEMyKSkKCmx1YWRfcGNhX3Bsb3QgPC0gbHVhZF9wY2FfdGVtcF9wbG90ICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3IgPSBnZW5kZXIpKQpsdWFkX3BjYV9wbG90CgpsdWFkX3BjYV9wbG90IDwtIGx1YWRfcGNhX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gcmFjZSkpCmx1YWRfcGNhX3Bsb3QKCmx1YWRfcGNhX3Bsb3QgPC0gbHVhZF9wY2FfdGVtcF9wbG90ICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3IgPSBldGhuaWNpdHkpKQpsdWFkX3BjYV9wbG90CgpsdWFkX3BjYV9wbG90IDwtIGx1YWRfcGNhX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gYWdlX2F0X2RpYWdub3NpcykpCmx1YWRfcGNhX3Bsb3QKCmx1YWRfcGNhX3Bsb3QgPC0gbHVhZF9wY2FfdGVtcF9wbG90ICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3IgPSB0aXNzdWVfc291cmNlX3NpdGUpKQpsdWFkX3BjYV9wbG90CgpsdWFkX3BjYV9wbG90IDwtIGx1YWRfcGNhX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gcGF0aG9sb2dpY19zdGFnZSkpCmx1YWRfcGNhX3Bsb3QKCmx1YWRfcGNhX3Bsb3QgPC0gbHVhZF9wY2FfdGVtcF9wbG90ICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3IgPSB0b2JhY2NvX3Ntb2tpbmdfaGlzdG9yeSkpCmx1YWRfcGNhX3Bsb3QKCmx1YWRfcGNhX3Bsb3QgPC0gbHVhZF9wY2FfdGVtcF9wbG90ICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3IgPSBzbW9rZXIpKQpsdWFkX3BjYV9wbG90CgpsdWFkX3BjYV9wbG90IDwtIGx1YWRfcGNhX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gaGlzdG9sb2dpY2FsX3R5cGUpKQpsdWFkX3BjYV9wbG90CmBgYAoKCmhpZXJhY2hpY2FsIGNsdXN0ZXJpbmcgdG8gc2VsZWN0IG91dGxpZXIgc2FtcGxlcwp1c2UgZGVmYXVsdCBkaXN0YW5jZSBtZWFzdXJlIChldWNsZWRpYW4pIGFuZCBhZ2dsb21lcmF0aW9uIG1ldGhvZCAoY29tcGxldGUpCmBgYHtyLCBmaWcud2lkdGg9MTJ9Cmx1YWRfaGMgPC0gaGNsdXN0KGRpc3QobHVhZF9tYXQpKQoKcGxvdChsdWFkX2hjLCBjZXggPSAwLjUpCgpsdWFkX2NsdXN0ZXJzIDwtIGN1dHJlZShsdWFkX2hjLCBoID0gMjAwKQpsdWFkX2NsdXN0ZXJzIDwtIHRpYmJsZShzYW1wbGUgPSBuYW1lcyhsdWFkX2NsdXN0ZXJzKSwgY2x1c3RlciA9IHVubmFtZShsdWFkX2NsdXN0ZXJzKSkKCndyaXRlX3Rzdih4ID0gbHVhZF9jbHVzdGVycywgZmlsZSA9ICIuL291dHB1dC9maWxlcy8wMl9leHBsb3JhdG9yeV9hbmFseXNpcy90Y2dhX2x1YWRfb3V0bGllcl9zYW1wbGVzX2hjbHVzdF8yMDBfaGVpZ2h0LnR4dCIpCgpsdWFkX3VtYXAyIDwtIHVtYXAobHVhZF9tYXRbcm93bmFtZXMobHVhZF9tYXQpICVpbiUgbHVhZF9jbHVzdGVyc1tsdWFkX2NsdXN0ZXJzJGNsdXN0ZXIgPT0gMSwgXSRzYW1wbGUsIF0pCgpsdWFkX3VtYXBfdGVtcF9wbG90MiA8LSBsdWFkX3VtYXAyICU+JQogIHBsdWNrKCJsYXlvdXQiKSAlPiUKICBhcy5kYXRhLmZyYW1lKCkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJzYW1wbGUiKSAlPiUKICBhc190aWJibGUoKSAlPiUKICByZW5hbWUoVU1BUDEgPSBWMSwgVU1BUDIgPSBWMikgJT4lCiAgaW5uZXJfam9pbihsdWFkX21ldGFkYXRhLCBieSA9ICJzYW1wbGUiKSAlPiUKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gVU1BUDEsIHkgPSBVTUFQMikpCgpsdWFkX3VtYXBfcGxvdDIgPC0gbHVhZF91bWFwX3RlbXBfcGxvdDIgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IHRpc3N1ZV9zb3VyY2Vfc2l0ZSkpCmx1YWRfdW1hcF9wbG90MgoKCmx1YWRfcGNhMiA8LSBwcmNvbXAobHVhZF9tYXRbcm93bmFtZXMobHVhZF9tYXQpICVpbiUgbHVhZF9jbHVzdGVyc1tsdWFkX2NsdXN0ZXJzJGNsdXN0ZXIgPT0gMSwgXSRzYW1wbGUsIF0sIGNlbnRlciA9IFQsIHNjYWxlLiA9IFQpCgpsdWFkX3BjYV90ZW1wX3Bsb3QyIDwtIGx1YWRfcGNhMiAlPiUKICBwbHVjaygieCIpICU+JQogIGFzLmRhdGEuZnJhbWUoKSAlPiUKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInNhbXBsZSIpICU+JQogIGFzX3RpYmJsZSgpICU+JQogIGlubmVyX2pvaW4obHVhZF9tZXRhZGF0YSwgYnkgPSAic2FtcGxlIikgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFBDMSwgeSA9IFBDMikpCgpsdWFkX3BjYV9wbG90MiA8LSBsdWFkX3BjYV90ZW1wX3Bsb3QyICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3IgPSB0aXNzdWVfc291cmNlX3NpdGUpKQpsdWFkX3BjYV9wbG90MgpgYGAKCgojIyMgZGltZW5zaW9uYWxpdHkgcmVkdWN0aW9uIGFjcm9zcyBMVVNDIGNvaG9ydAoKc2V0IHVwIGEgbWF0cml4IHdpdGggTFVTQyBjb2hvcnQKYGBge3J9Cmx1c2NfbWF0IDwtIGx1c2NfZnBrbSAlPiUKICBjb2x1bW5fdG9fcm93bmFtZXModmFyID0gImdlbmUiKSAlPiUKICBhcy5tYXRyaXgoKSAlPiUKICB0KCkKYGBgCgoKVU1BUCBhbmFseXNpcyBhY3Jvc3MgTFVTQyBjb2hvcnQKYGBge3J9Cmx1c2NfdW1hcCA8LSB1bWFwKGx1c2NfbWF0KQoKbHVzY191bWFwX3RlbXBfcGxvdCA8LSBsdXNjX3VtYXAgJT4lCiAgcGx1Y2soImxheW91dCIpICU+JQogIGFzLmRhdGEuZnJhbWUoKSAlPiUKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInNhbXBsZSIpICU+JQogIGFzX3RpYmJsZSgpICU+JQogIHJlbmFtZShVTUFQMSA9IFYxLCBVTUFQMiA9IFYyKSAlPiUKICBpbm5lcl9qb2luKGx1c2NfbWV0YWRhdGEsIGJ5ID0gInNhbXBsZSIpICU+JQogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBVTUFQMSwgeSA9IFVNQVAyKSkKCmx1c2NfdW1hcF9wbG90IDwtIGx1c2NfdW1hcF90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IGdlbmRlcikpCmx1c2NfdW1hcF9wbG90CgpsdXNjX3VtYXBfcGxvdCA8LSBsdXNjX3VtYXBfdGVtcF9wbG90ICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3IgPSByYWNlKSkKbHVzY191bWFwX3Bsb3QKCmx1c2NfdW1hcF9wbG90IDwtIGx1c2NfdW1hcF90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IGV0aG5pY2l0eSkpCmx1c2NfdW1hcF9wbG90CgpsdXNjX3VtYXBfcGxvdCA8LSBsdXNjX3VtYXBfdGVtcF9wbG90ICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3IgPSBhZ2VfYXRfZGlhZ25vc2lzKSkKbHVzY191bWFwX3Bsb3QKCmx1c2NfdW1hcF9wbG90IDwtIGx1c2NfdW1hcF90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IHRpc3N1ZV9zb3VyY2Vfc2l0ZSkpCmx1c2NfdW1hcF9wbG90CgpsdXNjX3VtYXBfcGxvdCA8LSBsdXNjX3VtYXBfdGVtcF9wbG90ICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3IgPSBwYXRob2xvZ2ljX3N0YWdlKSkKbHVzY191bWFwX3Bsb3QKCmx1c2NfdW1hcF9wbG90IDwtIGx1c2NfdW1hcF90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IHRvYmFjY29fc21va2luZ19oaXN0b3J5KSkKbHVzY191bWFwX3Bsb3QKCmx1c2NfdW1hcF9wbG90IDwtIGx1c2NfdW1hcF90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IHNtb2tlcikpCmx1c2NfdW1hcF9wbG90CgpsdXNjX3VtYXBfcGxvdCA8LSBsdXNjX3VtYXBfdGVtcF9wbG90ICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3IgPSBoaXN0b2xvZ2ljYWxfdHlwZSkpCmx1c2NfdW1hcF9wbG90CmBgYAoKClBDQSBhbmFseXNpcyBhY3Jvc3MgTFVTQyBjb2hvcnQKYGBge3J9Cmx1c2NfcGNhIDwtIHByY29tcChsdXNjX21hdCwgY2VudGVyID0gVCwgc2NhbGUuID0gVCkKCmx1c2NfcGNhX3RlbXBfcGxvdCA8LSBsdXNjX3BjYSAlPiUKICBwbHVjaygieCIpICU+JQogIGFzLmRhdGEuZnJhbWUoKSAlPiUKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInNhbXBsZSIpICU+JQogIGFzX3RpYmJsZSgpICU+JQogIGlubmVyX2pvaW4obHVzY19tZXRhZGF0YSwgYnkgPSAic2FtcGxlIikgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFBDMSwgeSA9IFBDMikpCgpsdXNjX3BjYV9wbG90IDwtIGx1c2NfcGNhX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gZ2VuZGVyKSkKbHVzY19wY2FfcGxvdAoKbHVzY19wY2FfcGxvdCA8LSBsdXNjX3BjYV90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IHJhY2UpKQpsdXNjX3BjYV9wbG90CgpsdXNjX3BjYV9wbG90IDwtIGx1c2NfcGNhX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gZXRobmljaXR5KSkKbHVzY19wY2FfcGxvdAoKbHVzY19wY2FfcGxvdCA8LSBsdXNjX3BjYV90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IGFnZV9hdF9kaWFnbm9zaXMpKQpsdXNjX3BjYV9wbG90CgpsdXNjX3BjYV9wbG90IDwtIGx1c2NfcGNhX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gdGlzc3VlX3NvdXJjZV9zaXRlKSkKbHVzY19wY2FfcGxvdAoKbHVzY19wY2FfcGxvdCA8LSBsdXNjX3BjYV90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IHBhdGhvbG9naWNfc3RhZ2UpKQpsdXNjX3BjYV9wbG90CgpsdXNjX3BjYV9wbG90IDwtIGx1c2NfcGNhX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gdG9iYWNjb19zbW9raW5nX2hpc3RvcnkpKQpsdXNjX3BjYV9wbG90CgpsdXNjX3BjYV9wbG90IDwtIGx1c2NfcGNhX3RlbXBfcGxvdCArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gc21va2VyKSkKbHVzY19wY2FfcGxvdAoKbHVzY19wY2FfcGxvdCA8LSBsdXNjX3BjYV90ZW1wX3Bsb3QgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvciA9IGhpc3RvbG9naWNhbF90eXBlKSkKbHVzY19wY2FfcGxvdApgYGAKCgpoaWVyYWNoaWNhbCBjbHVzdGVyaW5nIHRvIHNlbGVjdCBvdXRsaWVyIHNhbXBsZXMKdXNlIGRlZmF1bHQgZGlzdGFuY2UgbWVhc3VyZSAoZXVjbGVkaWFuKSBhbmQgYWdnbG9tZXJhdGlvbiBtZXRob2QgKGNvbXBsZXRlKQpgYGB7ciwgZmlnLndpZHRoPTEyfQpsdXNjX2hjIDwtIGhjbHVzdChkaXN0KGx1c2NfbWF0KSkKCnBsb3QobHVzY19oYywgY2V4ID0gMC41KQoKbHVzY19jbHVzdGVycyA8LSBjdXRyZWUobHVzY19oYywgaCA9IDE5MCkKbHVzY19jbHVzdGVycyA8LSB0aWJibGUoc2FtcGxlID0gbmFtZXMobHVzY19jbHVzdGVycyksIGNsdXN0ZXIgPSB1bm5hbWUobHVzY19jbHVzdGVycykpCgp3cml0ZV90c3YoeCA9IGx1c2NfY2x1c3RlcnMsIGZpbGUgPSAiLi9vdXRwdXQvZmlsZXMvMDJfZXhwbG9yYXRvcnlfYW5hbHlzaXMvdGNnYV9sdXNjX291dGxpZXJfc2FtcGxlc19oY2x1c3RfMTkwX2hlaWdodC50eHQiKQoKbHVzY191bWFwMiA8LSB1bWFwKGx1c2NfbWF0W3Jvd25hbWVzKGx1c2NfbWF0KSAlaW4lIGx1c2NfY2x1c3RlcnNbbHVzY19jbHVzdGVycyRjbHVzdGVyID09IDEsIF0kc2FtcGxlLCBdKQoKbHVzY191bWFwX3RlbXBfcGxvdDIgPC0gbHVzY191bWFwMiAlPiUKICBwbHVjaygibGF5b3V0IikgJT4lCiAgYXMuZGF0YS5mcmFtZSgpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAic2FtcGxlIikgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgcmVuYW1lKFVNQVAxID0gVjEsIFVNQVAyID0gVjIpICU+JQogIGlubmVyX2pvaW4obHVzY19tZXRhZGF0YSwgYnkgPSAic2FtcGxlIikgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFVNQVAxLCB5ID0gVU1BUDIpKQoKbHVzY191bWFwX3Bsb3QyIDwtIGx1c2NfdW1hcF90ZW1wX3Bsb3QyICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3IgPSBzbW9rZXIpKQpsdXNjX3VtYXBfcGxvdDIKCgpsdXNjX3BjYTIgPC0gcHJjb21wKGx1c2NfbWF0W3Jvd25hbWVzKGx1c2NfbWF0KSAlaW4lIGx1c2NfY2x1c3RlcnNbbHVzY19jbHVzdGVycyRjbHVzdGVyID09IDEsIF0kc2FtcGxlLCBdLCBjZW50ZXIgPSBULCBzY2FsZS4gPSBUKQoKbHVzY19wY2FfdGVtcF9wbG90MiA8LSBsdXNjX3BjYTIgJT4lCiAgcGx1Y2soIngiKSAlPiUKICBhcy5kYXRhLmZyYW1lKCkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJzYW1wbGUiKSAlPiUKICBhc190aWJibGUoKSAlPiUKICBpbm5lcl9qb2luKGx1c2NfbWV0YWRhdGEsIGJ5ID0gInNhbXBsZSIpICU+JQogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBQQzEsIHkgPSBQQzIpKQoKbHVzY19wY2FfcGxvdDIgPC0gbHVzY19wY2FfdGVtcF9wbG90MiArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKGNvbG9yID0gc21va2VyKSkKbHVzY19wY2FfcGxvdDIKYGBgCgo=